package com.kakarote.hrm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.kakarote.core.common.MultipartFileUtil;
import com.kakarote.core.common.Result;
import com.kakarote.core.common.cache.AdminCacheKey;
import com.kakarote.core.common.cache.HrmCacheKey;
import com.kakarote.core.common.enums.DataAuthEnum;
import com.kakarote.core.common.enums.FieldEnum;
import com.kakarote.core.common.enums.SystemCodeEnum;
import com.kakarote.core.entity.BasePage;
import com.kakarote.core.entity.UploadEntity;
import com.kakarote.core.exception.CrmException;
import com.kakarote.core.feign.admin.service.AdminFileService;
import com.kakarote.core.feign.admin.service.AdminService;
import com.kakarote.core.redis.Redis;
import com.kakarote.core.servlet.BaseServiceImpl;
import com.kakarote.core.utils.ExcelParseUtil;
import com.kakarote.core.utils.RecursionUtil;
import com.kakarote.core.utils.UserUtil;
import com.kakarote.hrm.common.EmployeeHolder;
import com.kakarote.hrm.common.HrmCodeEnum;
import com.kakarote.hrm.constant.*;
import com.kakarote.hrm.entity.BO.AddDeptBO;
import com.kakarote.hrm.entity.BO.DeptMoveBO;
import com.kakarote.hrm.entity.BO.QueryDeptListBO;
import com.kakarote.hrm.entity.BO.QueryEmployeeByDeptIdBO;
import com.kakarote.hrm.entity.BO.export.DeptExportBO;
import com.kakarote.hrm.entity.PO.*;
import com.kakarote.hrm.entity.VO.*;
import com.kakarote.hrm.mapper.*;
import com.kakarote.hrm.service.*;
import com.kakarote.hrm.utils.EmployeeUtil;
import com.kakarote.hrm.utils.HttpUtils;
import io.seata.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 部门表 服务实现类
 * </p>
 *
 * @author huangmingbo
 * @since 2020-05-12
 */
@Slf4j
@Service
public class HrmDeptServiceImpl extends BaseServiceImpl<HrmDeptMapper, HrmDept> implements IHrmDeptService {

    @Autowired
    private HrmDeptMapper deptMapper;

    @Autowired
    private IHrmEmployeeService employeeService;

    @Autowired
    private HrmEmployeeDataMapper employeeDataMapper;

    @Autowired
    private AdminService adminService;

    @Autowired
    private EmployeeUtil employeeUtil;

    @Autowired
    private Redis redis;

    @Autowired
    private IHrmEmployeeDataService employeeDataService;
    @Resource
    private AdminFileService adminFileService;

    @Autowired
    private HrmEmployeeDataChangeRecordMapper employeeDataChangeRecordMapper;

    @Autowired
    private HrmEmployeeDataIntegrityMapper employeeDataIntegrityMapper;

    @Autowired
    private HrmEmployeeDataMobilizeRecordMapper employeeDataMobilizeRecordMapper;

    @Autowired
    private IHrmEmployeeDataChangeRecordService employeeDataChangeRecordService;

    @Autowired
    private HrmEmployeeMapper employeeMapper;

    @Autowired
    private IHrmDataPushLogService dataPushLogService;

    @Autowired
    private HrmPushDataDetailMapper pushDataDetailMapper;

    @Value("${pushData.dept.get}")
    private String deptGetUrl;
    @Value("${pushData.dept.add}")
    private String deptAddUrl;
    @Value("${pushData.dept.update}")
    private String deptUpdateUrl;
    @Value("${pushData.dept.delete}")
    private String deptDeleteUrl;

    /**
     * 树结构根据指定部门重组
     *
     * @param result      返回接过
     * @param node        全部树结构
     * @param findDeptIds 需要筛选的部门id
     */
    private static void filterNode(DeptVO result, DeptVO node, Set<Long> findDeptIds) {
        List<DeptVO> childList = node.getChildren();
        if (findDeptIds.contains(node.getDeptId())) {
            DeptVO newNode = BeanUtil.copyProperties(node, DeptVO.class);
            newNode.setChildren(null);
            if (CollUtil.isEmpty(result.getChildren())) {
                result.setChildren(Lists.newArrayList(newNode));
            } else {
                List<DeptVO> childList1 = result.getChildren();
                childList1.add(newNode);
            }
            findDeptIds.remove(node.getDeptId());
            if (CollUtil.isEmpty(childList)) {
                return;
            }
            for (DeptVO deptVO : childList) {
                filterNode(newNode, deptVO, findDeptIds);
            }
        } else {
            if (CollUtil.isEmpty(childList)) {
                return;
            }
            for (DeptVO deptVO : childList) {
                filterNode(result, deptVO, findDeptIds);
            }
        }
    }

    @Override
    @Transactional
    public HrmDept addOrUpdate(AddDeptBO addDeptBO) {
        HrmDept hrmDept = BeanUtil.copyProperties(addDeptBO, HrmDept.class);
//        boolean exists;
//        if (addDeptBO.getDeptId() == null) {
//            exists = lambdaQuery().eq(HrmDept::getCode, addDeptBO.getCode()).exists();
//        } else {
//            exists = lambdaQuery().eq(HrmDept::getCode, addDeptBO.getCode()).ne(HrmDept::getDeptId, addDeptBO.getDeptId()).exists();
//        }
//        if (exists) {
//            throw new CrmException(HrmCodeEnum.DEPT_CODE_ALREADY_EXISTS);
//        }
        //同级部门不允许名称重复
        if (addDeptBO.getDeptId() == null) {
            boolean exists = lambdaQuery().eq(HrmDept::getName, addDeptBO.getName()).eq(HrmDept::getParentId, addDeptBO.getParentId()).exists();
            if (exists) {
                throw new CrmException(HrmCodeEnum.DEPT_SAME_LEVEL_NAME_ALREADY_EXISTS);
            }
        } else {
            boolean exists = lambdaQuery().eq(HrmDept::getName, addDeptBO.getName()).ne(HrmDept::getDeptId, addDeptBO.getDeptId()).eq(HrmDept::getParentId, addDeptBO.getParentId()).exists();
            if (exists) {
                throw new CrmException(HrmCodeEnum.DEPT_SAME_LEVEL_NAME_ALREADY_EXISTS);
            }
        }
        if (Objects.equals(hrmDept.getParentId(), hrmDept.getDeptId())) {
            //校验部门编号是否等于父级部门编号
            throw new CrmException(HrmCodeEnum.DEPT_PARENT_ID_UPDATE_ERROR);
        }
        //更新level
        if (hrmDept.getParentId() != 0) {
            HrmDept parentDept = deptMapper.selectById(hrmDept.getParentId());
            if (parentDept.getDeptType() == 2 && hrmDept.getDeptType() == 1) {
                throw new CrmException(HrmCodeEnum.DEPT_STRUCTURE_ERROR);
            }
            hrmDept.setLevel(parentDept.getLevel() + 1);
        } else {
            hrmDept.setLevel(1);
        }
        hrmDept.setCode(createDeptCode(hrmDept));
        //获取机构版块
        if (hrmDept.getDeptType() == HrmDeptTypeEnum.DEPARTMENT.getValue()) {
            DeptVO companyDept = getCompanyDeptId(hrmDept.getDeptId());
            if (companyDept != null) {
                hrmDept.setOrgSector(companyDept.getOrgSector());
                hrmDept.setUnitProperties(companyDept.getUnitProperties());
                hrmDept.setOrgType(companyDept.getOrgType());
            }
        }
        String remark = getChangeRecordRemark(hrmDept);
        if (hrmDept.getSortId() != null) {
            //更新部门sortId
            HrmDept d = new HrmDept();
            d.setParentId(hrmDept.getParentId());
            d.setSortId(hrmDept.getSortId() - 1);
            deptMapper.updateDeptSortByPid(d);
        }
        saveOrUpdate(hrmDept);
//        if (companyDept != null){
//            List<Long> deptIds = selectChildrenDeptIds(companyDept.getDeptId());
//            lambdaUpdate().in(HrmDept::getDeptId,deptIds).eq(HrmDept::getDeptType,2).set(HrmDept::getOrgSector,companyDept.getOrgSector())
//                    .update();
//        }
        //保存部门修改记录
        HrmEmployeeDataChangeRecord record = new HrmEmployeeDataChangeRecord();
        record.setType(EmployeeDataChangeType.DEPT.getValue());
        record.setDeptId(hrmDept.getDeptId());
        record.setSubDeptId(EmployeeHolder.getEmployeeInfo().getDeptId());
        record.setSubEmployeeId(EmployeeHolder.getEmployeeInfo().getEmployeeId());
        record.setRemark(remark);
        employeeDataChangeRecordService.addChangeRecord(record);
        return hrmDept;
    }

    private String getChangeRecordRemark(HrmDept newDept) {
        StringBuffer sb = new StringBuffer();
        if (newDept.getDeptId() == null) {
            sb.append(String.format("员工 %s 新建了组织部门名称为 %s，组织类型为 %s，上级组织为%s，组织编码为%s。",
                    EmployeeHolder.getEmployeeInfo().getEmployeeName(), newDept.getName(), newDept.getDeptType(), newDept.getParentId(), newDept.getCode()));
            if (newDept.getMainEmployeeId() != null) {
                sb.append(String.format("组织负责人为：%s 。", newDept.getMainEmployeeId()));
            }
            if (StrUtil.isNotEmpty(newDept.getLeaderEmployeeId())) {
                sb.append(String.format("分管领导为：%s。", newDept.getLeaderEmployeeId()));
            }
            if (newDept.getOrgSector() != null) {
                sb.append(String.format("机构板块为：%s。", newDept.getOrgSector()));
            }
            if (newDept.getUnitProperties() != null) {
                sb.append(String.format("单位性质为：%s。", newDept.getUnitProperties()));
            }
            if (newDept.getOrgType() != null) {
                sb.append(String.format("组织性质为：%s。", newDept.getOrgType()));
            }
            if (newDept.getSortId() != null) {
                sb.append(String.format("排序为：%s。", newDept.getSortId()));
            }
            if (newDept.getSectionChiefPreparation() != null) {
                sb.append(String.format("正处编制人数为：%s。", newDept.getSectionChiefPreparation()));
            }
            if (newDept.getDeputySectionChiefPreparation() != null) {
                sb.append(String.format("副处编制人数为：%s。", newDept.getDeputySectionChiefPreparation()));
            }
            if (newDept.getDirectorPreparation() != null) {
                sb.append(String.format("正科编制人数为：%s。", newDept.getDirectorPreparation()));
            }
            if (newDept.getDeputyDirectorPreparation() != null) {
                sb.append(String.format("副科编制人数为：%s。", newDept.getDeputyDirectorPreparation()));
            }
        } else {
            HrmDept oldDept = deptMapper.selectById(newDept.getDeptId());
            sb.append(String.format("员工 %s 编辑了组织部门编号为 %s。",
                    EmployeeHolder.getEmployeeInfo().getEmployeeName(), newDept.getDeptId()));
            if (!Objects.equals(oldDept.getName(), newDept.getName())) {
                sb.append(String.format("将组织部门名称，由%s修改为%s。", oldDept.getName(), newDept.getName()));
            }
            if (!Objects.equals(oldDept.getDeptType(), newDept.getDeptType())) {
                sb.append(String.format("将组织类型，由%s修改为%s。", oldDept.getDeptType(), newDept.getDeptType()));
            }
            if (!Objects.equals(oldDept.getParentId(), newDept.getParentId())) {
                sb.append(String.format("将上级组织，由%s修改为%s。", oldDept.getParentId() != null ? oldDept.getParentId() : "空", newDept.getParentId() != null ? newDept.getParentId() : "空"));
            }
            if (!Objects.equals(oldDept.getMainEmployeeId(), newDept.getMainEmployeeId())) {
                sb.append(String.format("将组织负责人，由%s修改为%s。", oldDept.getMainEmployeeId() != null ? oldDept.getMainEmployeeId() : "空", newDept.getMainEmployeeId() != null ? newDept.getMainEmployeeId() : "空"));
            }
            if (!Objects.equals(oldDept.getLeaderEmployeeId(), newDept.getLeaderEmployeeId())) {
                sb.append(String.format("将分管领导，由%s修改为%s。", oldDept.getLeaderEmployeeId() != null ? oldDept.getLeaderEmployeeId() : "空", newDept.getLeaderEmployeeId() != null ? newDept.getLeaderEmployeeId() : "空"));
            }
            if (!Objects.equals(oldDept.getOrgSector(), newDept.getOrgSector())) {
                sb.append(String.format("将机构板块，由%s修改为%s。", oldDept.getOrgSector() != null ? oldDept.getOrgSector() : "空", newDept.getOrgSector() != null ? newDept.getOrgSector() : "空"));
            }
            if (!Objects.equals(oldDept.getUnitProperties(), newDept.getUnitProperties())) {
                sb.append(String.format("将单位性质，由%s修改为%s。", oldDept.getUnitProperties() != null ? oldDept.getUnitProperties() : "空", newDept.getUnitProperties() != null ? newDept.getUnitProperties() : "空"));
            }
            if (!Objects.equals(oldDept.getOrgType(), newDept.getOrgType())) {
                sb.append(String.format("将组织性质，由%s修改为%s。", oldDept.getOrgType() != null ? oldDept.getOrgType() : "空", newDept.getOrgType() != null ? newDept.getOrgType() : "空"));
            }
            if (!Objects.equals(oldDept.getSortId(), newDept.getSortId())) {
                sb.append(String.format("将排序，由%s修改为%s。", oldDept.getSortId() != null ? oldDept.getSortId() : "空", newDept.getSortId() != null ? newDept.getSortId() : "空"));
            }
            if (!Objects.equals(oldDept.getSectionChiefPreparation(), newDept.getSectionChiefPreparation())) {
                sb.append(String.format("将正处编制人数，由%s修改为%s。", oldDept.getSectionChiefPreparation() != null ? oldDept.getSectionChiefPreparation() : "空", newDept.getSectionChiefPreparation() != null ? newDept.getSectionChiefPreparation() : "空"));
            }
            if (!Objects.equals(oldDept.getDeputySectionChiefPreparation(), newDept.getDeputySectionChiefPreparation())) {
                sb.append(String.format("将副处编制人数，由%s修改为%s。", oldDept.getDeputySectionChiefPreparation() != null ? oldDept.getDeputySectionChiefPreparation() : "空", newDept.getDeputySectionChiefPreparation() != null ? newDept.getDeputySectionChiefPreparation() : "空"));
            }
            if (!Objects.equals(oldDept.getDirectorPreparation(), newDept.getDirectorPreparation())) {
                sb.append(String.format("将正科编制人数，由%s修改为%s。", oldDept.getDirectorPreparation() != null ? oldDept.getDirectorPreparation() : "空", newDept.getDirectorPreparation() != null ? newDept.getDirectorPreparation() : "空"));
            }
            if (!Objects.equals(oldDept.getDeputyDirectorPreparation(), newDept.getDeputyDirectorPreparation())) {
                sb.append(String.format("将副科编制人数，由%s修改为%s。", oldDept.getDeputyDirectorPreparation() != null ? oldDept.getDeputyDirectorPreparation() : "空", newDept.getDeputyDirectorPreparation() != null ? newDept.getDeputyDirectorPreparation() : "空"));
            }
        }
        return sb.toString();
    }

    private DeptVO getCompanyDeptId(Long deptId) {
        DeptVO companyDept = null;
        List<DeptVO> deptList = deptMapper.selectAllDeptList();
        if (deptList != null && !deptList.isEmpty()) {
            Map<Long, DeptVO> group = deptList.stream().collect(Collectors.toMap(DeptVO::getDeptId, v -> v));
            while (true) {
                if (group.containsKey(deptId)) {
                    DeptVO dept = group.get(deptId);
                    if (dept.getDeptType() == 1 && dept.getLevel() > 1) {
                        companyDept = dept;
                    }
                    deptId = dept.getParentId();
                } else {
                    break;
                }
            }
        }
        return companyDept;
    }

    private String createDeptCode(HrmDept hrmDept) {
        StringBuffer sb = new StringBuffer();
        sb.append(String.format("%02d", Optional.ofNullable(hrmDept.getLevel()).orElse(0)));
        sb.append(Optional.ofNullable(hrmDept.getDeptType()).orElse(0));
        sb.append(Optional.ofNullable(hrmDept.getOrgSector()).orElse(0));
        sb.append(Optional.ofNullable(hrmDept.getUnitProperties()).orElse(0));
        sb.append(Optional.ofNullable(hrmDept.getOrgType()).orElse(0));
        sb.append("-");
        if (hrmDept.getDeptId() == null) {
            sb.append(String.format("%06d", redis.incr(HrmCacheKey.HRM_DEPT_NO)));
        } else {
            HrmDept dept = deptMapper.selectById(hrmDept.getDeptId());
            if (dept.getCode().length() >= 6) {
                sb.append(dept.getCode().substring(dept.getCode().length() - 6));
            } else {
                sb.append(dept.getCode());
            }
        }
        return sb.toString();
    }

    @Override
    public DeptVO queryById(Long deptId) {
        Collection<Long> employeeIds = employeeUtil.queryDataAuthEmpIdByMenuId(MenuIdConstant.EMPLOYEE_MENU_ID);
//        boolean exists = false;
//        if (CollUtil.isNotEmpty(employeeIds)) {
//            exists = employeeService.lambdaQuery().eq(HrmEmployee::getDeptId, deptId).in(HrmEmployee::getEmployeeId, employeeIds).exists();
//        }
        if (CollUtil.isNotEmpty(employeeIds)) {
            DeptVO deptVO = deptMapper.queryById(deptId, new ArrayList<>());
            List<DeptVO> deptTree = createDeptTotalTree(0L, deptMapper.queryList(new QueryDeptListBO()));
            List<DeptVO> result = new ArrayList<>();
            getTreeAllNode(result, deptTree);
            for (DeptVO dept : result) {
                if (Objects.equals(dept.getDeptId(), deptId)) {
                    deptVO.setTotalNum(dept.getTotalNum());
                    deptVO.setSectionChiefPreparation(dept.getSectionChiefPreparation());
                    deptVO.setDeputySectionChiefPreparation(dept.getDeputySectionChiefPreparation());
                    deptVO.setDirectorPreparation(dept.getDirectorPreparation());
                    deptVO.setDeputyDirectorPreparation(dept.getDeputyDirectorPreparation());
                    deptVO.setSectionChiefNum(dept.getSectionChiefNum());
                    deptVO.setDeputySectionChiefNum(dept.getDeputySectionChiefNum());
                    deptVO.setDirectorNum(dept.getDirectorNum());
                    deptVO.setDeputyDirectorNum(dept.getDeputyDirectorNum());
                    deptVO.setUnderOrganization(dept.getUnderOrganization());
                    deptVO.setLackPreparation(dept.getLackPreparation());
                    deptVO.setContractTotal(dept.getContractTotal());
                    deptVO.setDispatchTotal(dept.getDispatchTotal());
                    deptVO.setOutsourceTotal(dept.getOutsourceTotal());
                    deptVO.setTemporaryTotal(dept.getTemporaryTotal());
                    deptVO.setRetireTotal(dept.getRetireTotal());
                    deptVO.setExternalTotal(dept.getExternalTotal());
                }
            }
            return deptVO;
        }
        return deptMapper.queryNoEmployeeDept(deptId);
    }

    @Override
    public List<DeptVO> queryTreeList(QueryDeptListBO queryDeptListBO) {
        List<Integer> dataAuthTypeList = adminService.queryDataTypeList(UserUtil.getUserId(), MenuIdConstant.DEPT_MENU_ID).getData();
        if (queryDeptListBO.getIsAdmin() != null && queryDeptListBO.getIsAdmin()) {
            dataAuthTypeList.add(DataAuthEnum.ALL.getValue());
        }
        List<DeptVO> deptVOList = new ArrayList<>();
        if (EmployeeHolder.isHrmAdmin() || dataAuthTypeList.contains(DataAuthEnum.ALL.getValue())) {
            String tree = "tree";
            if (tree.equals(queryDeptListBO.getType()) || queryDeptListBO.getType() == null) {
                List<DeptVO> deptList = deptMapper.queryList(queryDeptListBO);
                deptVOList = createDeptTotalTree(0L, deptList);
                if (StrUtil.isNotEmpty(queryDeptListBO.getName())) {
                    deptVOList = doSearch(deptVOList, queryDeptListBO.getName());
                }
            }
            String update = "update";
            if (update.equals(queryDeptListBO.getType())) {
                List<HrmDept> deptList = list();
                deptVOList = deptList.stream().map(dept -> {
                    DeptVO deptVO = new DeptVO();
                    deptVO.setDeptId(dept.getDeptId());
                    deptVO.setName(dept.getName());
                    deptVO.setParentId(dept.getParentId());
                    return deptVO;
                }).collect(Collectors.toList());
                List<Long> ids = RecursionUtil.getChildList(deptVOList, "parentId", queryDeptListBO.getId(), "deptId", "deptId");
                ids.add(queryDeptListBO.getId());
                deptVOList.removeIf(dept -> ids.contains(dept.getDeptId()));
            }
        } else {
            if (dataAuthTypeList != null && !dataAuthTypeList.isEmpty()) {
                deptVOList = getDataAuthDeptList(queryDeptListBO, dataAuthTypeList);
            }
        }
        return deptVOList;
    }

    /**
     * tree 关键字搜索
     *
     * @param searchList
     * @param keyWord
     * @return
     */
    private List<DeptVO> doSearch(List<DeptVO> searchList, String keyWord) {
        List<DeptVO> resultList = new ArrayList<>();
        if (searchList == null || searchList.isEmpty()) {
            return resultList;
        }
        for (DeptVO treeVo : searchList) {
            // 判断是否包括keyWord
            String projectName = treeVo.getName();
            if (projectName.contains(keyWord)) {
                // 如果存在关键字继续递归子集
                treeVo.setChildren(doSearch(treeVo.getChildren(), keyWord));
                resultList.add(treeVo);
            } else {
                // 继续递归
                List<DeptVO> children = doSearch(treeVo.getChildren(), keyWord);
                if (!children.isEmpty()) {
                    // 把子节点列表加到节点上
                    treeVo.setChildren(children);
                    resultList.add(treeVo);
                }
            }
        }
        return resultList;
    }

    @Override
    public List<DeptVO> createDeptTotalTree(Long pid, List<DeptVO> deptList) {
        if (deptList != null && !deptList.isEmpty()) {
            Collection<Long> employeeIds = employeeUtil.queryUserDataAuthEmpIdByMenuId(MenuIdConstant.EMPLOYEE_MENU_ID);
            employeeIds.add(-1L);
            // 在编人数
            List<HrmEmployee> underEmp = deptMapper.getDeptUnderOrganizationEmployee(employeeIds);
            Map<Long, Long> underMap = new HashMap<>();
            if (underEmp != null && !underEmp.isEmpty()) {
                underMap = underEmp.stream().collect(Collectors.groupingBy(HrmEmployee::getDeptId, Collectors.counting()));
            }
            // 实有人数
            List<HrmEmployee> realityEmp = deptMapper.getDeptRealityEmployee(employeeIds);
            Map<Long, Set<Long>> realityMap = new HashMap<>();
            if (realityEmp != null && !realityEmp.isEmpty()) {
                realityMap = realityEmp.stream().collect(Collectors.groupingBy(HrmEmployee::getDeptId, Collectors.mapping(HrmEmployee::getEmployeeId, Collectors.toSet())));
            }
            // 用工形式统计
            List<DeptVO> workForms = deptMapper.getDeptEmployeeWorkFormsTotal(employeeIds);
            Map<Long, DeptVO> workFormsMap = new HashMap<>();
            if (workForms != null && !workForms.isEmpty()) {
                workFormsMap = workForms.stream().collect(Collectors.toMap(DeptVO::getDeptId, e -> e));
            }

            // 查询正处现配备人数
            List<HrmEmployee> sectionChiefEmpList = deptMapper.getSectionChiefNum(employeeIds);
            Map<Long, Long> sectionChiefMap = sectionChiefEmpList.stream().collect(Collectors.groupingBy(HrmEmployee::getDeptId, Collectors.counting()));

            // 查询副处现配备人数
            List<HrmEmployee> deputySectionChiefEmpList = deptMapper.getDeputySectionChiefNum(employeeIds);
            Map<Long, Long> deputySectionChiefMap = deputySectionChiefEmpList.stream().collect(Collectors.groupingBy(HrmEmployee::getDeptId, Collectors.counting()));

            // 查询正科现配备人数
            List<HrmEmployee> directorEmpList = deptMapper.getDirectorNum(employeeIds);
            Map<Long, Long> directorMap = directorEmpList.stream().collect(Collectors.groupingBy(HrmEmployee::getDeptId, Collectors.counting()));

            // 查询副科现配备人数
            List<HrmEmployee> deputyDirectorEmpList = deptMapper.getDeputyDirectorNum(employeeIds);
            Map<Long, Long> deputyDirectorMap = deputyDirectorEmpList.stream().collect(Collectors.groupingBy(HrmEmployee::getDeptId, Collectors.counting()));

            Map<Long, List<DeptVO>> deptMap = deptList.stream().collect(Collectors.groupingBy(DeptVO::getParentId, Collectors.toList()));
            List<DeptVO> deptRoot = deptMap.get(pid);
            getChildrenTotalDept(deptRoot, deptMap, underMap, realityMap, workFormsMap, sectionChiefMap, deputySectionChiefMap, directorMap, deputyDirectorMap);
            return deptRoot;
        }
        return deptList;
    }

    private void getChildrenTotalDept(List<DeptVO> deptRoot, Map<Long, List<DeptVO>> deptMap, Map<Long, Long> underMap, Map<Long, Set<Long>> realityEmp, Map<Long, DeptVO> workFormsMap, Map<Long, Long> sectionChiefMap, Map<Long, Long> deputySectionChiefMap, Map<Long, Long> directorMap, Map<Long, Long> deputyDirectorMap) {
        if (deptRoot != null && !deptRoot.isEmpty()) {
            for (DeptVO dept : deptRoot) {
                //用工形式
                if (workFormsMap.containsKey(dept.getDeptId())) {
                    dept.setContractTotal(workFormsMap.get(dept.getDeptId()).getContractTotal());
                    dept.setDispatchTotal(workFormsMap.get(dept.getDeptId()).getDispatchTotal());
                    dept.setOutsourceTotal(workFormsMap.get(dept.getDeptId()).getOutsourceTotal());
                    dept.setTemporaryTotal(workFormsMap.get(dept.getDeptId()).getTemporaryTotal());
                    dept.setRetireTotal(workFormsMap.get(dept.getDeptId()).getRetireTotal());
                    dept.setExternalTotal(workFormsMap.get(dept.getDeptId()).getExternalTotal());
                }
                dept.setEmpIds(Optional.ofNullable(realityEmp.get(dept.getDeptId())).orElse(new HashSet<>()));
                dept.setUnderOrganization(Optional.ofNullable(underMap.get(dept.getDeptId())).orElse(0L));
                dept.setSectionChiefNum(Optional.ofNullable(sectionChiefMap.get(dept.getDeptId())).orElse(0L));
                dept.setDeputySectionChiefNum(Optional.ofNullable(deputySectionChiefMap.get(dept.getDeptId())).orElse(0L));
                dept.setDirectorNum(Optional.ofNullable(directorMap.get(dept.getDeptId())).orElse(0L));
                dept.setDeputyDirectorNum(Optional.ofNullable(deputyDirectorMap.get(dept.getDeptId())).orElse(0L));
                List<DeptVO> children = deptMap.get(dept.getDeptId());
                getChildrenTotalDept(children, deptMap, underMap, realityEmp, workFormsMap, sectionChiefMap, deputySectionChiefMap, directorMap, deputyDirectorMap);
                if (CollUtil.isNotEmpty(children)) {
                    children = children.stream().sorted(Comparator.comparing(DeptVO::getSortId, Comparator.nullsLast(Long::compare)).thenComparing(DeptVO::getDeptId)).collect(Collectors.toList());
                    dept.setChildren(children);
                    Set<Long> collect = children.stream().map(DeptVO::getEmpIds).flatMap(Collection::stream).collect(Collectors.toSet());
                    dept.getEmpIds().addAll(collect);
                    // 在编人数
                    dept.setSectionChiefPreparation(dept.getSectionChiefPreparation() + children.stream().mapToLong(DeptVO::getSectionChiefPreparation).sum());
                    dept.setDeputySectionChiefPreparation(dept.getDeputySectionChiefPreparation() + children.stream().mapToLong(DeptVO::getDeputySectionChiefPreparation).sum());
                    dept.setDirectorPreparation(dept.getDirectorPreparation() + children.stream().mapToLong(DeptVO::getDirectorPreparation).sum());
                    dept.setDeputyDirectorPreparation(dept.getDeputyDirectorPreparation() + children.stream().mapToLong(DeptVO::getDeputyDirectorPreparation).sum());
                    dept.setSectionChiefNum(dept.getSectionChiefNum() + children.stream().mapToLong(DeptVO::getSectionChiefNum).sum());
                    dept.setDeputySectionChiefNum(dept.getDeputySectionChiefNum() + children.stream().mapToLong(DeptVO::getDeputySectionChiefNum).sum());
                    dept.setDirectorNum(dept.getDirectorNum() + children.stream().mapToLong(DeptVO::getDirectorNum).sum());
                    dept.setDeputyDirectorNum(dept.getDeputyDirectorNum() + children.stream().mapToLong(DeptVO::getDeputyDirectorNum).sum());
                    //用工形式
                    dept.setUnderOrganization(dept.getUnderOrganization() + children.stream().mapToLong(DeptVO::getUnderOrganization).sum());
                    dept.setContractTotal(children.stream().mapToInt(DeptVO::getContractTotal).sum() + dept.getContractTotal());
                    dept.setDispatchTotal(children.stream().mapToInt(DeptVO::getDispatchTotal).sum() + dept.getDispatchTotal());
                    dept.setOutsourceTotal(children.stream().mapToInt(DeptVO::getOutsourceTotal).sum() + dept.getOutsourceTotal());
                    dept.setTemporaryTotal(children.stream().mapToInt(DeptVO::getTemporaryTotal).sum() + dept.getTemporaryTotal());
                    dept.setRetireTotal(children.stream().mapToInt(DeptVO::getRetireTotal).sum() + dept.getRetireTotal());
                    dept.setExternalTotal(children.stream().mapToInt(DeptVO::getExternalTotal).sum() + dept.getExternalTotal());
                }
                //实有人数
                dept.setTotalNum((long) dept.getEmpIds().size());
                //缺编人数
//                dept.setLackPreparation(dept.getConfirmPreparation() - dept.getUnderOrganization());
            }
        }
    }

    private void getTreeAllNode(List<DeptVO> result, List<DeptVO> deptList) {
        deptList.forEach(item -> {
            result.add(item);
            if (item.getChildren() != null && !item.getChildren().isEmpty()) {
                getTreeAllNode(result, item.getChildren());
                item.setChildren(null);
            }
        });
    }

    /**
     * 部门数据权限搜索
     */
    private List<DeptVO> getDataAuthDeptList(QueryDeptListBO queryDeptListBO, List<Integer> dataAuthTypeList) {
        /*List<DeptVO> deptVOList = new ArrayList<>();
        Collection<Long> employeeIds = employeeUtil.queryDataAuthEmpId(dataAuthType, MenuIdConstant.DEPT_MENU_ID);
        if (CollUtil.isEmpty(employeeIds)) {
            return deptVOList;
        }
        List<DeptVO> queryDept = deptMapper.queryDeptByEmpIds(employeeIds);
        Map<Long, DeptVO> deptIdMap = queryDept.stream().collect(Collectors.toMap(DeptVO::getDeptId, e -> e));
        Set<Long> deptIds = employeeUtil.queryDataAuthDeptId(dataAuthType, MenuIdConstant.DEPT_MENU_ID);
        List<DeptVO> deptList = deptMapper.queryList(queryDeptListBO);
        for (DeptVO deptVO : deptList) {
            if (deptIdMap.containsKey(deptVO.getDeptId())) {
                DeptVO dept = deptIdMap.get(deptVO.getDeptId());
                deptVO.setAllNum(dept.getAllNum());
                deptVO.setMyAllNum(dept.getMyAllNum());
                deptVO.setFullTimeNum(dept.getFullTimeNum());
                deptVO.setMyFullTimeNum(dept.getMyFullTimeNum());
                deptVO.setNuFullTimeNum(dept.getNuFullTimeNum());
                deptVO.setMyNuFullTimeNum(dept.getNuFullTimeNum());
            } else {
                deptVO.setAllNum(0);
                deptVO.setMyAllNum(0);
                deptVO.setFullTimeNum(0);
                deptVO.setMyFullTimeNum(0);
                deptVO.setNuFullTimeNum(0);
                deptVO.setMyNuFullTimeNum(0);
            }
        }
        if (StrUtil.isNotEmpty(queryDeptListBO.getName())) {
            List<HrmDept> list = lambdaQuery().select(HrmDept::getDeptId).in(HrmDept::getDeptId, deptIds).like(HrmDept::getName, queryDeptListBO.getName()).list();
            for (HrmDept dept : list) {
                deptVOList.addAll(createTree1(dept.getDeptId(), deptList));
            }
            return deptVOList;
        } else {
            List<DeptVO> treeDept = createTree(0L, deptList);
            DeptVO root = new DeptVO();
            if (CollUtil.isNotEmpty(treeDept)) {
                filterNode(root, treeDept.get(0), deptIds);
            }
            deptVOList = root.getChildren();
            return deptVOList;
        }*/
        Set<Long> deptIds = employeeUtil.queryDataAuthDeptId(dataAuthTypeList, MenuIdConstant.DEPT_MENU_ID);
        deptIds.add(-1L);
        queryDeptListBO.setDeptIds(deptIds);
        List<DeptVO> deptList = deptMapper.queryList(queryDeptListBO);
        return createDeptTotalTree(0L, deptList);
    }

    private List<DeptVO> createTree(Long pid, List<DeptVO> deptList) {
        List<DeptVO> treeDept = new ArrayList<>();
        for (DeptVO dept : deptList) {
            if (pid.equals(dept.getParentId())) {
                treeDept.add(dept);
                List<DeptVO> children = createTree(dept.getDeptId(), deptList);
                for (DeptVO child : children) {
//                    dept.setAllNum(dept.getAllNum() + child.getAllNum());
                    dept.setAllNum(dept.getAllNum());
                    dept.setFullTimeNum(dept.getFullTimeNum() + child.getFullTimeNum());
                    dept.setNuFullTimeNum(dept.getNuFullTimeNum() + child.getNuFullTimeNum());
                }
                dept.setChildren(children);
            }
        }
        return treeDept;
    }

    private List<DeptVO> createTree1(Long id, List<DeptVO> deptList) {
        List<DeptVO> treeDept = new ArrayList<>();
        for (DeptVO dept : deptList) {
            if (id.equals(dept.getDeptId())) {
                treeDept.add(dept);
                List<DeptVO> children = createTree(dept.getDeptId(), deptList);
                for (DeptVO child : children) {
                    dept.setAllNum(dept.getAllNum() + child.getAllNum());
                    dept.setFullTimeNum(dept.getFullTimeNum() + child.getFullTimeNum());
                    dept.setNuFullTimeNum(dept.getNuFullTimeNum() + child.getNuFullTimeNum());
                }
            }
        }
        return treeDept;
    }

    @Override
    public List<SimpleHrmDeptVO> querySimpleDeptList(Collection<Long> deptIds) {
        if (CollUtil.isEmpty(deptIds)) {
            return new ArrayList<>();
        }
        return lambdaQuery().select(HrmDept::getDeptId, HrmDept::getName, HrmDept::getParentId)
                .in(HrmDept::getDeptId, deptIds)
                .list()
                .stream().map(dept -> {
                    SimpleHrmDeptVO simpleHrmDeptVO = new SimpleHrmDeptVO();
                    simpleHrmDeptVO.setDeptId(dept.getDeptId());
                    simpleHrmDeptVO.setParentId(dept.getParentId());
                    simpleHrmDeptVO.setDeptName(dept.getName());
                    return simpleHrmDeptVO;
                }).collect(Collectors.toList());
    }

    @Override
    public SimpleHrmDeptVO querySimpleDept(Long deptId) {
        if (deptId == null) {
            return new SimpleHrmDeptVO();
        }
        HrmDept hrmDept = lambdaQuery().select(HrmDept::getDeptId, HrmDept::getName).eq(HrmDept::getDeptId, deptId).one();
        SimpleHrmDeptVO simpleHrmDeptVO = new SimpleHrmDeptVO();
        simpleHrmDeptVO.setDeptId(hrmDept.getDeptId());
        simpleHrmDeptVO.setDeptName(hrmDept.getName());
        return simpleHrmDeptVO;
    }

    @Override
    public BasePage<QueryEmployeeListByDeptIdVO> queryEmployeeByDeptId(QueryEmployeeByDeptIdBO employeeByDeptIdBO) {
        Collection<Long> employeeIds = employeeUtil.queryDataAuthEmpIdByMenuId(MenuIdConstant.DEPT_MENU_ID);
//        Collection<Long> employeeIds = employeeUtil.queryUserDataAuthEmpIdByMenuId(MenuIdConstant.DEPT_MENU_ID);
        if (employeeByDeptIdBO.getDeptId() != null) {
            //部门检索
            List<Long> deptIds = selectChildrenDeptIds(employeeByDeptIdBO.getDeptId());
            employeeByDeptIdBO.setChildrenDeptIdList(deptIds);
            employeeByDeptIdBO.setDeptId(null);
        }
        BasePage<QueryEmployeeListByDeptIdVO> page = deptMapper.queryEmployeeByDeptId(employeeByDeptIdBO.parse(), employeeByDeptIdBO, employeeIds);
        List<QueryEmployeeListByDeptIdVO> list = page.getList();
        if (list != null && !list.isEmpty()) {
            List<Long> empIdList = list.stream().map(QueryEmployeeListByDeptIdVO::getEmployeeId).collect(Collectors.toList());
            List<HrmEmployeeData> dataList = employeeDataService.lambdaQuery().in(HrmEmployeeData::getEmployeeId, empIdList).list();
            if (dataList != null && !dataList.isEmpty()) {
                Map<Long, Map<String, String>> dataGroup = dataList.stream().collect(Collectors.groupingBy(HrmEmployeeData::getEmployeeId, Collectors.toMap(HrmEmployeeData::getFieldName, e -> Optional.ofNullable(e.getFieldValue()).orElse(""), (d1, d2) -> d2)));

                List<DeptVO> deptVOS = deptMapper.selectAllDeptList();
                Map<Long, String> deptMap = new HashMap<>();
                if (deptVOS != null && !deptVOS.isEmpty()) {
                    deptMap = deptVOS.stream().collect(Collectors.toMap(DeptVO::getDeptId, DeptVO::getName, (v1, v2) -> v2));
                }
                for (QueryEmployeeListByDeptIdVO emp : list) {
                    Map<String, String> map = dataGroup.get(emp.getEmployeeId());
                    if (StringUtils.isNotEmpty(map.get("dept"))) {
                        emp.setDeptName(deptMap.get(Long.valueOf(map.get("dept"))));
                    }
                    if (StringUtils.isNotEmpty(map.get("org"))) {
                        emp.setOrgName(deptMap.get(Long.valueOf(map.get("org"))));
                    }
                    emp.setDuties(map.get("job_title"));
                    emp.setJobLevel(map.get("job_level"));
                    emp.setPolName(map.get("pol_id"));
                    emp.setPostStatus(map.get("post_status"));
                    emp.setWorkForms(map.get("work_forms"));
                }
            }
        }
        return page;
    }

    @Override
    public List<Long> queryEmployeeIdListByDeptId(Long deptId) {
        List<Long> deptIds = selectChildrenDeptIds(deptId);
        return employeeMapper.queryEmployeeIdListByDeptId(deptIds);
    }

    @Override
    public int pushDeptData(List<Long> deptIds) {
        log.info("开始部门同步数据");
        List<DeptDetailInforVO> deptDetails = deptMapper.selectPushDeptData(deptIds);
        Map<String, DeptDetailInforVO> deptDetailMap = new HashMap<>();
        if (!deptDetails.isEmpty()) {
            deptDetailMap = deptDetails.stream().collect(Collectors.toMap(DeptDetailInforVO::getDeptCode, v -> v));
        }
        log.info("人资部门empDetailMap数据：{}", JSON.toJSON(deptDetailMap));
        //同步数据
        List<DeptDetailInforVO> addList = new ArrayList<>();
        List<DeptDetailInforVO> updateList = new ArrayList<>();
        List<String> deleteList = new ArrayList<>();
        //市政部门数据
        List<DeptResultVo> deptResultVos = new ArrayList<>();
        String resultStr = HttpUtils.createGetHttp(deptGetUrl, new HashMap<>());
        if (StrUtil.isNotEmpty(resultStr)) {
            JSONObject jsonObject = JSONObject.parseObject(resultStr);
            String text = jsonObject.getString("result");
            if (StrUtil.isNotEmpty(text)) {
                JSONArray jsonarray = JSONArray.parseArray(text);
                for (int n = 0; n < jsonarray.size(); n++) {
                    JSONObject json = jsonarray.getJSONObject(n);
                    DeptResultVo deptResultVo = JSON.parseObject(String.valueOf(json), DeptResultVo.class);
                    deptResultVos.add(deptResultVo);
                }
            }
        }
        Map<String, DeptResultVo> deptResultMap = new HashMap<>();
        if (!deptResultVos.isEmpty()) {
            deptResultMap = deptResultVos.stream().collect(Collectors.toMap(DeptResultVo::getDeptmentCode, v -> v));
        }
        log.info("市政部门deptResultMap数据：{}", JSON.toJSON(deptResultMap));

        for (Long deptId : deptIds) {
            if (deptDetailMap.containsKey(deptId.toString()) && !deptResultMap.containsKey(deptId.toString())) {
                addList.add(deptDetailMap.get(deptId.toString()));
            } else if (!deptDetailMap.containsKey(deptId.toString()) && deptResultMap.containsKey(deptId.toString())) {
                deleteList.add(deptId.toString());
            } else {
                updateList.add(deptDetailMap.get(deptId.toString()));
            }
        }
        log.info("对比完成");
        //同步日志详情
        List<HrmDataPushDetail> details = new ArrayList<>();
        //删除
        for (String code : deleteList) {
            Map<String, String> map = new HashMap();
            map.put("deptCode", code);
            String result = HttpUtils.createPostHttp(deptDeleteUrl, map);
            if (StrUtil.isNotEmpty(result)) {
                details.add(JSONObject.parseObject(result, HrmDataPushDetail.class));
            }
        }
        log.info("删除推送成功");
        //新增
        for (DeptDetailInforVO dept : addList) {
            Map<String, String> map = new HashMap();
            map.put("deptDetailInfor", JSON.toJSONString(dept));
            String result = HttpUtils.createPostHttp(deptAddUrl, map);
            if (StrUtil.isNotEmpty(result)) {
                details.add(JSONObject.parseObject(result, HrmDataPushDetail.class));
            }
        }
        log.info("新增推送成功");
        //修改
        for (DeptDetailInforVO dept : updateList) {
            Map<String, String> map = new HashMap();
            map.put("deptDetailInfor", JSON.toJSONString(dept));
            String result = HttpUtils.createPostHttp(deptUpdateUrl, map);
            if (StrUtil.isNotEmpty(result)) {
                details.add(JSONObject.parseObject(result, HrmDataPushDetail.class));
            }
        }
        log.info("修改推送成功");
        log.info("推送完成");
        //推送记录
        HrmDataPushLog l = new HrmDataPushLog();
        l.setType(PushDataTypeEnum.DEPT.getType());
        l.setRemark("部门数据单独推送");
        boolean save = dataPushLogService.save(l);
        log.info("推送记录保存完成");
        //保存推送详情
        if (save && !details.isEmpty()) {
            for (HrmDataPushDetail detail : details) {
                detail.setPushId(l.getId());
                detail.setCreateUserId(UserUtil.getUserId());
            }
            pushDataDetailMapper.batchInsert(details);
        }
        log.info("推送详情保存完成");
        return save ? 1 : 0;
    }

    @Override
    public List<QueryEmployeeListByDeptIdVO> queryManageEmployeeByDeptId(QueryEmployeeByDeptIdBO employeeByDeptIdBO) {
        if (employeeByDeptIdBO.getDeptId() != null) {
            //部门下非公司部门
            List<Long> deptIds = selectChildrenManageDeptIds(employeeByDeptIdBO.getDeptId());
            employeeByDeptIdBO.setChildrenDeptIdList(deptIds);
        }
        List<QueryEmployeeListByDeptIdVO> queryEmployeeListByDeptIdVOS = deptMapper.queryManageEmployeeByDeptId(employeeByDeptIdBO);
        //查询部门组织负责人、分管领导列表
        HrmDept hrmDept = deptMapper.selectById(employeeByDeptIdBO.getDeptId());
        if (hrmDept != null) {
            ArrayList<Long> empIds = new ArrayList<>();
            if (hrmDept.getMainEmployeeId() != null) {
                empIds.add(hrmDept.getMainEmployeeId());
            }
            if (StrUtil.isNotEmpty(hrmDept.getLeaderEmployeeId())) {
                String[] split = hrmDept.getLeaderEmployeeId().split(",");
                Arrays.stream(split).filter(StrUtil::isNotEmpty).map(Long::valueOf).forEach(empIds::add);
            }
            Set<Long> empIdSet = new HashSet<>();
            if (queryEmployeeListByDeptIdVOS != null && !queryEmployeeListByDeptIdVOS.isEmpty()) {
                empIdSet = queryEmployeeListByDeptIdVOS.stream().map(QueryEmployeeListByDeptIdVO::getEmployeeId).collect(Collectors.toSet());
            }
            empIds.removeIf(empIdSet::contains);
            if (!empIds.isEmpty()) {
                List<HrmEmployee> employeeList = employeeService.lambdaQuery().in(HrmEmployee::getEmployeeId, empIds).eq(HrmEmployee::getIsDel, 0).list();
                for (HrmEmployee emp : employeeList) {
                    QueryEmployeeListByDeptIdVO vo = new QueryEmployeeListByDeptIdVO();
                    vo.setEmployeeId(emp.getEmployeeId());
                    vo.setEmployeeName(emp.getEmployeeName());
                    vo.setMobile(emp.getMobile());
                    queryEmployeeListByDeptIdVOS.add(vo);
                }
            }
        }
        return queryEmployeeListByDeptIdVOS;
    }

    private List<Long> selectChildrenManageDeptIds(Long deptId) {
        ArrayList<Long> longs = new ArrayList<>();
        longs.add(deptId);
        List<DeptVO> deptList = deptMapper.selectAllDeptList();
        if (deptList != null && !deptList.isEmpty()) {
            Map<Long, List<DeptVO>> deptGroup = deptList.stream().collect(Collectors.groupingBy(DeptVO::getParentId));
            Map<Long, DeptVO> deprMap = deptList.stream().collect(Collectors.toMap(DeptVO::getDeptId, v -> v));
            DeptVO deptVO = deprMap.get(deptId);
            if (deptVO != null) {
                return getManageChildrenDeptId(deptGroup, deptGroup.get(deptVO.getParentId()), longs, deptVO);
            }
        }
        return longs;
    }

    private List<Long> getManageChildrenDeptId(Map<Long, List<DeptVO>> deptGroup, List<DeptVO> deptList, ArrayList<Long> result, DeptVO deptVO) {
        if (deptList != null && !deptList.isEmpty()) {
            for (DeptVO dept : deptList) {
                if (dept.getDeptType() != 1 || Objects.equals(dept.getDeptId(), deptVO.getDeptId()) || deptVO.getParentId().equals(0L)) {
                    result.add(dept.getDeptId());
                    getManageChildrenDeptId(deptGroup, deptGroup.get(dept.getDeptId()), result, deptVO);
                }
            }
        }
        return result;
    }

    @Override
    public void deleteDeptById(String deptId) {
//        boolean exists = employeeService.lambdaQuery().in(HrmEmployee::getEntryStatus, 1, 3).eq(HrmEmployee::getDeptId, deptId).eq(HrmEmployee::getIsDel, 0).exists();
        int count = employeeMapper.queryDeptIsExistEmployee(deptId);
        if (count > 0) {
            throw new CrmException(HrmCodeEnum.THERE_ARE_EMPLOYEES_UNDER_THE_DEPARTMENT);
        }
        boolean childExists = lambdaQuery().eq(HrmDept::getParentId, deptId).exists();
        if (childExists) {
            throw new CrmException(HrmCodeEnum.THERE_ARE_SUB_DEPARTMENTS_THAT_CANNOT_BE_DELETED);
        }
        HrmDept dept = getById(deptId);
        String one = "01100-000001";
        if (one.equals(dept.getCode())) {
            throw new CrmException(HrmCodeEnum.TOP_LEVEL_DEPARTMENT_CANNOT_BE_DELETED);
        }
        //保存部门修改记录
        HrmEmployeeDataChangeRecord record = new HrmEmployeeDataChangeRecord();
        record.setType(EmployeeDataChangeType.DEPT.getValue());
        record.setDeptId(Long.parseLong(deptId));
        record.setSubDeptId(EmployeeHolder.getEmployeeInfo().getDeptId());
        record.setSubEmployeeId(EmployeeHolder.getEmployeeInfo().getEmployeeId());
        record.setRemark(String.format("员工 %s 删除了组织部门，组织部门编号为 %s，组织部门名称为%s。", EmployeeHolder.getEmployeeInfo().getEmployeeName(), deptId, dept.getName()));
        employeeDataChangeRecordService.addChangeRecord(record);
        removeById(deptId);
    }

    @Override
    public Set<Long> queryChildDeptId(Collection<Long> deptIds) {
        Set<Long> newDeptIds = new HashSet<>(deptIds);
        if (CollUtil.isNotEmpty(deptIds)) {
            deptIds.forEach(deptId -> {
                List<Long> childList = RecursionUtil.getChildList(list(), "parentId", deptId, "deptId", "deptId");
                newDeptIds.addAll(childList);
            });
        }
        return newDeptIds;
    }

    @Override
    public Set<Long> queryParentDeptId(Long pid) {
        Set<Long> deptIds = new HashSet<>();
        deptIds.add(pid);
        Optional<HrmDept> hrmDeptOpt = lambdaQuery().select(HrmDept::getDeptId, HrmDept::getParentId).eq(HrmDept::getDeptId, pid).oneOpt();
        if (hrmDeptOpt.isPresent()) {
            HrmDept hrmDept = hrmDeptOpt.get();
            if (ObjectUtil.notEqual(0L, hrmDept.getParentId())) {
                Set<Long> integers = queryParentDeptId(hrmDept.getParentId());
                deptIds.addAll(integers);
            }
        }
        return deptIds;
    }

    @Override
    public List<DeptEmployeeVO> queryDeptEmployeeList() {
        return deptMapper.queryDeptEmployeeList();
    }


    @Override
    public Long getEmployeeDeptId(Long employeeId, String type) {
        String deptId = employeeDataMapper.getEmployeeFieldValue(employeeId, type);
        if (StringUtils.isNotEmpty(deptId)) {
            return Long.parseLong(deptId);
        }
        return null;
    }

    @Override
    public Set<Long> getDeptChildrenByEmployeeId(Long employeeId) {
        String deptId = employeeDataMapper.getEmployeeFieldValue(employeeId, "dept");
        if (StringUtils.isNotEmpty(deptId)) {
            List<Long> longs = selectChildrenDeptIds(Long.parseLong(deptId));
            return new HashSet<>(longs);
        }
        Set<Long> depts = new HashSet<>();
        depts.add(-1L);
        return depts;
    }

    @Override
    public Set<Long> getOrgChildrenByEmployeeId(Long employeeId) {
        String deptId = employeeDataMapper.getEmployeeFieldValue(employeeId, "org");
        if (StringUtils.isNotEmpty(deptId)) {
            List<Long> longs = selectChildrenDeptIds(Long.parseLong(deptId));
            return new HashSet<>(longs);
        }
        Set<Long> depts = new HashSet<>();
        depts.add(-1L);
        return depts;
    }

    @Override
    public String getDeptPathByEmployeeId(Long employeeId) {
        List<String> deptNameList = new ArrayList<>();
        String deptId = employeeDataMapper.getEmployeeFieldValue(employeeId, "dept");
        if (StringUtils.isNotEmpty(deptId)) {
            List<DeptVO> deptList = deptMapper.selectAllDeptList();
            if (deptList != null && !deptList.isEmpty()) {
                Map<Long, DeptVO> group = deptList.stream().collect(Collectors.toMap(DeptVO::getDeptId, v -> v));
                getDeptPath(deptNameList, group, Long.parseLong(deptId));
            }
        }
        return String.join("/", deptNameList);
    }

    private List<String> getDeptPath(List<String> deptNameList, Map<Long, DeptVO> group, Long deptId) {
        if (group.containsKey(deptId)) {
            getDeptPath(deptNameList, group, group.get(deptId).getParentId());
            deptNameList.add(group.get(deptId).getName());
        }
        return deptNameList;
    }

    @Override
    public List<Long> selectChildrenDeptIds(Set<Long> deptIds) {
        ArrayList<Long> longs = new ArrayList<>(deptIds);
        List<DeptVO> deptList = deptMapper.selectAllDeptList();
        if (deptList != null && !deptList.isEmpty()) {
            Map<Long, List<DeptVO>> deptGroup = deptList.stream().collect(Collectors.groupingBy(DeptVO::getParentId));
            for (int i = 0; i < longs.size(); i++) {
                getChildrenDeptId(deptGroup, longs.get(i), longs);
            }
        }
        return longs;
    }

    @Override
    public List<Long> selectChildrenDeptIds(Long deptId) {
        ArrayList<Long> longs = new ArrayList<>();
        longs.add(deptId);
        List<DeptVO> deptList = deptMapper.selectAllDeptList();
        if (deptList != null && !deptList.isEmpty()) {
            Map<Long, List<DeptVO>> deptGroup = deptList.stream().collect(Collectors.groupingBy(DeptVO::getParentId));
            return getChildrenDeptId(deptGroup, deptId, longs);
        }
        return longs;
    }

    private List<Long> getChildrenDeptId(Map<Long, List<DeptVO>> deptGroup, Long deptId, ArrayList<Long> result) {
        if (deptGroup.containsKey(deptId)) {
            List<DeptVO> deptList = deptGroup.get(deptId);
            if (!deptList.isEmpty()) {
                for (DeptVO dept : deptList) {
                    result.add(dept.getDeptId());
                    getChildrenDeptId(deptGroup, dept.getDeptId(), result);
                }
            }
        }
        return result;
    }

    @Override
    public void deptMove(DeptMoveBO deptMoveBO) {
        HrmDept oldDept = deptMapper.selectById(deptMoveBO.getDeptId());
        //修改sortId
        HrmDept hrmDept = new HrmDept();
        if (!oldDept.getParentId().equals(deptMoveBO.getParentId())) {
            //上移 下移 才需要修改level
            if (deptMoveBO.getParentId() != 0) {
                HrmDept parentDept = deptMapper.selectById(deptMoveBO.getParentId());
                Integer level = parentDept.getLevel();
                oldDept.setLevel(level + 1);
                hrmDept.setLevel(level + 1);
            } else {
                oldDept.setLevel(1);
                hrmDept.setLevel(1);
            }
            List<Long> longs = new ArrayList<>();
            longs.add(-1L);
            List<DeptVO> deptList = deptMapper.queryList(new QueryDeptListBO());
            if (deptList != null && !deptList.isEmpty()) {
                Map<Long, List<DeptVO>> deptGroup = deptList.stream().collect(Collectors.groupingBy(DeptVO::getParentId));
                List<DeptVO> deptRoot = deptGroup.get(deptMoveBO.getDeptId());
                getMoveDeptIdList(deptRoot, deptGroup, longs);
            }
            deptMapper.updateDeptLevelByIdList(longs);
        }

        if (deptMoveBO.getFrontId() != 0) {
            //前面存在部门
            HrmDept frontDept = deptMapper.selectById(deptMoveBO.getFrontId());
            hrmDept.setSortId(frontDept.getSortId());
            oldDept.setSortId(frontDept.getSortId() + 1);
        } else {
            //前面不存在部门 第一个部门
            hrmDept.setSortId(0L);
            oldDept.setSortId(1L);
        }
        deptMapper.updateDeptSortByPid(hrmDept);

        deptMapper.updateDeptLevelSortById(oldDept);
    }

    private void getMoveDeptIdList(List<DeptVO> deptRoot, Map<Long, List<DeptVO>> deptGroup, List<Long> deptList) {
        if (!deptRoot.isEmpty()) {
            deptRoot.stream().forEach(item -> {
                deptList.add(item.getDeptId());
                List<DeptVO> depts = new ArrayList<>();
                if (deptGroup.containsKey(item.getDeptId())) {
                    depts = deptGroup.get(item.getDeptId());
                }
                getMoveDeptIdList(depts, deptGroup, deptList);
            });
        }
    }

    @Override
    public List<HrmDept> exportDeptList() {
        List<HrmDept> list = lambdaQuery().eq(HrmDept::getLevel, 2).list();
        if (list != null && !list.isEmpty()) {
            list = list.stream().sorted(Comparator.comparing(HrmDept::getSortId, Comparator.nullsLast(Long::compare)).thenComparing(HrmDept::getDeptId)).collect(Collectors.toList());
        }
        return list;
    }

    @Override
    public void exportExcel(HttpServletResponse response, List<Long> deptIds) throws IOException {
        if (deptIds != null && !deptIds.isEmpty()) {
            //文件名及编码方式，System.currentTimeMillis()为当前系统的时间戳
            String filename = URLEncoder.encode(String.valueOf(System.currentTimeMillis()), "utf-8");
            //设置响应头信息：将响应内容类型设置为 Excel 文件，并指定文件名和编码方式
            response.setHeader("Content-Disposition", "attachment;filename=" + filename + ".xlsx");
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");

            Map<Long, List<DeptExportBO>> exportData = new HashMap<>();
            // 全部部门
            List<DeptExportBO> deptList = deptMapper.selectExportData();
            Map<String, DeptExportBO> deptMap;
            Map<String, List<DeptExportBO>> deptGroup = new HashMap<>();
            if (deptList != null && !deptList.isEmpty()) {
                deptMap = deptList.stream().collect(Collectors.toMap(DeptExportBO::getDeptId, Function.identity(), (v1, v2) -> v2));
                deptGroup = deptList.stream().collect(Collectors.groupingBy(DeptExportBO::getParentId));
            } else {
                deptMap = new HashMap<>();
            }
            // 全部员工
            List<HrmEmployee> employeeList = employeeService.lambdaQuery().eq(HrmEmployee::getIsDel, 0).list();
            Map<Long, String> employeeMap = new HashMap<>();
            if (employeeList != null && !employeeList.isEmpty()) {
                employeeMap = employeeList.stream().collect(Collectors.toMap(HrmEmployee::getEmployeeId, HrmEmployee::getEmployeeName, (v1, v2) -> v2));
            }
            getExportData(exportData, deptGroup, employeeMap, deptIds, deptMap);
            try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build()) {
                int i = 0;
                Set<Long> depeIdSet = exportData.keySet();
                List<DeptExportBO> deptExportBOList = depeIdSet.stream().map(item -> deptMap.get(item.toString())).collect(Collectors.toList());
                //排序
                deptExportBOList.sort(Comparator.comparing(DeptExportBO::getSortId, Comparator.nullsLast(Long::compare)).thenComparing(item -> Long.parseLong(item.getDeptId())));

                for (DeptExportBO dept : deptExportBOList) {
                    Long deptId = Long.valueOf(dept.getDeptId());
                    List<DeptExportBO> dataValue = exportData.get(deptId);
                    String deptName = deptMap.get(deptId.toString()).getName();
                    WriteSheet writeSheet = EasyExcel.writerSheet(++i, deptName).head(DeptExportBO.class).build();
                    // 填充数据
                    excelWriter.write(dataValue, writeSheet);
                }
            }
        }

    }

    private void getExportData(Map<Long, List<DeptExportBO>> exportData, Map<String, List<DeptExportBO>> deptGroup, Map<Long, String> employeeMap, List<Long> deptIds, Map<String, DeptExportBO> deptMap) {
        for (Long deptId : deptIds) {
            List<DeptExportBO> deptExportBOList = new ArrayList<>();
            List<DeptExportBO> deptList = new ArrayList<>();
            deptList.add(deptMap.get(deptId.toString()));
            getDeptList(deptList, deptGroup, employeeMap, deptExportBOList);
            exportData.put(deptId, deptExportBOList);
        }
    }

    private void getDeptList(List<DeptExportBO> deptList, Map<String, List<DeptExportBO>> deptGroup, Map<Long, String> employeeMap, List<DeptExportBO> deptExportBOList) {
        if (deptList != null && !deptList.isEmpty()) {
            for (DeptExportBO deptExportBO : deptList) {
                deptExportBOList.add(deptExportBO);
                deptExportBO.setMainEmployeeName(employeeMap.get(deptExportBO.getMainEmployeeId()));
                String leaderEmployeeId = deptExportBO.getLeaderEmployeeId();
                if (StringUtils.isNotEmpty(leaderEmployeeId)) {
                    String[] split = leaderEmployeeId.split(",");
                    deptExportBO.setLeaderEmployeeName(Arrays.stream(split).map(id -> employeeMap.get(Long.valueOf(id))).collect(Collectors.joining(",")));
                }
                deptExportBO.setDeptTypeCn(deptExportBO.getDeptType() == 1 ? "公司" : "部门");
                deptExportBO.setOrgSectorCn(OrgSectorEnum.getNameByValue(deptExportBO.getOrgSector()));
                deptExportBO.setUnitPropertiesCn(UnitPropertiesEnum.getNameByValue(deptExportBO.getUnitProperties()));
                deptExportBO.setOrgTypeCn(OrgTypeEnum.getNameByValue(deptExportBO.getOrgType()));
                List<DeptExportBO> children = deptGroup.get(deptExportBO.getDeptId());
                getDeptList(children, deptGroup, employeeMap, deptExportBOList);
                if (children != null && !children.isEmpty()) {
                    deptExportBO.setSectionChiefPreparation(children.stream().mapToLong(item -> Optional.ofNullable(item.getSectionChiefPreparation()).orElse(0L)).sum());
                    deptExportBO.setSectionChiefNum(children.stream().mapToLong(item -> Optional.ofNullable(item.getSectionChiefNum()).orElse(0L)).sum());
                    deptExportBO.setDeputySectionChiefPreparation(children.stream().mapToLong(item -> Optional.ofNullable(item.getDeputySectionChiefPreparation()).orElse(0L)).sum());
                    deptExportBO.setDeputySectionChiefNum(children.stream().mapToLong(item -> Optional.ofNullable(item.getDeputySectionChiefNum()).orElse(0L)).sum());
                    deptExportBO.setDirectorPreparation(children.stream().mapToLong(item -> Optional.ofNullable(item.getDirectorPreparation()).orElse(0L)).sum());
                    deptExportBO.setDirectorNum(children.stream().mapToLong(item -> Optional.ofNullable(item.getDirectorNum()).orElse(0L)).sum());
                    deptExportBO.setDeputyDirectorPreparation(children.stream().mapToLong(item -> Optional.ofNullable(item.getDeputyDirectorPreparation()).orElse(0L)).sum());
                    deptExportBO.setDeputyDirectorNum(children.stream().mapToLong(item -> Optional.ofNullable(item.getDeputyDirectorNum()).orElse(0L)).sum());
                }
            }
        }
    }

    @Override
    public void downloadExcel(HttpServletResponse response) {
        List<JSONObject> list = queryField();
        ExcelParseUtil.importExcel(new ExcelParseUtil.ExcelParseService() {
            @Override
            public String getExcelName() {
                return "部门";
            }

            @Override
            public String getMergeContent(String module) {
                return "注意事项：\n" +
                        "1、表头标“*”的红色字体为必填项\n" +
                        "2、组织类型：只能填写[公司、部门]\n" +
                        "3、组织负责人：目前只支持单人，填写员工名称\n" +
                        "4、组织负责人电话：填写对应组织负责人电话，只有组织负责人+电话都填写才能导入\n" +
                        "5、分管领导：支持多人，填写员工名称，多个员工使用\",\"分割，例如“张三,李四,王五”\n" +
                        "6、分管领导电话：填写对应分管领导电话，顺序要一致，只有分管领导+电话都填写才能导入”\n" +
                        "7、机构板块：只能填写[集团总部、公用事业、金融投资、现代农业、工程地产、其他板块]\n" +
                        "8、单位性质：只能填写[合并报表企业、托管企业、其他]\n" +
                        "9、编制人数：只有最底层部门需要填写\n" +
                        "10、组织编码：填写表示修改，不填则会新增\n";
            }
        }, list, response, "user");
    }

    private List<JSONObject> queryField() {
        List<JSONObject> list = new ArrayList<>();
        list.add(queryField("name", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "部门名称", 1));
        list.add(queryField("deptType", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "组织类型", 1));
        list.add(queryField("parentCode", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "上级组织编码", 1));
        list.add(queryField("mainEmployeeName", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "组织负责人", 0));
        list.add(queryField("mainEmployeePhone", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "组织负责人电话", 0));
        list.add(queryField("leaderEmployeeName", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "分管领导", 0));
        list.add(queryField("leaderEmployeePhone", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "分管领导电话", 0));
        list.add(queryField("orgSectorName", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "机构板块", 0));
        list.add(queryField("unitPropertiesName", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "单位性质", 0));
        list.add(queryField("orgTypeName", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "组织性质", 0));
        list.add(queryField("sortId", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "排序号", 0));
        list.add(queryField("section_chief_preparation", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "正处编制人数", 0));
        list.add(queryField("section_chief_num", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "正处现配备人数", 0));
        list.add(queryField("deputy_section_chief_preparation", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "副处编制人数", 0));
        list.add(queryField("deputy_section_chief_num", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "副处现配备人数", 0));
        list.add(queryField("director_preparation", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "正科编制人数", 0));
        list.add(queryField("director_num", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "正科现配备人数", 0));
        list.add(queryField("deputy_director_preparation", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "副科编制人数", 0));
        list.add(queryField("deputy_director_num", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "副科现配备人数", 0));
        list.add(queryField("code", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "组织编码", 0));
        return list;
    }

    private JSONObject queryField(String fieldName, String formType, Integer type, String name, Integer isNull) {
        JSONObject json = new JSONObject();
        json.fluentPut("fieldName", fieldName)
                .fluentPut("formType", formType)
                .fluentPut("type", type)
                .fluentPut("name", name).fluentPut("isNull", isNull);
        return json;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JSONObject excelImport(MultipartFile file) {
        List<List<Object>> errList = new ArrayList<>();
        String filePath = getFilePath(file);
        AtomicReference<Integer> num = new AtomicReference<>(0);
        //新增部门
        List<HrmDept> addDeptList = new ArrayList<>();
        //部门数据
        List<HrmDept> depeList = lambdaQuery().list();
        Map<String, HrmDept> codeMap;
        if (depeList != null && !depeList.isEmpty()) {
            codeMap = depeList.stream().collect(Collectors.toMap(HrmDept::getCode, Function.identity(), (v1, v2) -> v2));
        } else {
            codeMap = new HashMap<>();
        }
        //获取员工数据
        List<HrmEmployee> employeeList = employeeService.lambdaQuery().select(HrmEmployee::getEmployeeId, HrmEmployee::getEmployeeName, HrmEmployee::getMobile).eq(HrmEmployee::getIsDel, 0).list();
        Map<String, Long> employeeMap;
        if (employeeList != null && !employeeList.isEmpty()) {
            employeeMap = employeeList.stream().collect(Collectors.toMap(item -> item.getEmployeeName() + ":" + item.getMobile(), HrmEmployee::getEmployeeId, (v1, v2) -> v2));
        } else {
            employeeMap = new HashMap<>();
        }
        ExcelUtil.readBySax(filePath, 0, (int sheetIndex, long rowIndex, List<Object> rowList) -> {
            if (rowIndex > 1) {
                num.getAndSet(num.get() + 1);
                if (rowList.size() < 12) {
                    int size = rowList.size();
                    for (int i = 0; i < 12 - size; i++) {
                        rowList.add("");
                    }
                }
                if (StrUtil.isEmptyIfStr(rowList.get(0).toString().trim())) {
                    rowList.add(0, "部门名称不能为空");
                    errList.add(rowList);
                    return;
                }
                if (StrUtil.isEmptyIfStr(rowList.get(1).toString().trim())) {
                    rowList.add(0, "组织类型不能为空");
                    errList.add(rowList);
                    return;
                } else {
                    String deptType = rowList.get(1).toString().trim();
                    if (!"公司".equals(deptType) && !"部门".equals(deptType)) {
                        rowList.add(0, "组织类型只能填写[公司、部门]");
                        errList.add(rowList);
                        return;
                    }
                }
                if (StrUtil.isEmptyIfStr(rowList.get(2).toString().trim())) {
                    rowList.add(0, "上级组织编码不能为空");
                    errList.add(rowList);
                    return;
                } else {
                    if (!codeMap.containsKey(rowList.get(2).toString().trim())) {
                        rowList.add(0, "上级组织编码不存在");
                        errList.add(rowList);
                        return;
                    }
                }
                Long mainId = null;
                if (!StrUtil.isEmptyIfStr(rowList.get(3).toString().trim()) && !StrUtil.isEmptyIfStr(rowList.get(4).toString().trim())) {
                    if (!employeeMap.containsKey(rowList.get(3).toString().trim() + ":" + rowList.get(4).toString().trim())) {
                        rowList.add(0, "组织负责人不存在，请确认员工名称和电话是否有误");
                        errList.add(rowList);
                        return;
                    }
                    mainId = employeeMap.get(rowList.get(3).toString().trim() + ":" + rowList.get(4).toString().trim());
                }
                String leaderIds = null;
                if (!StrUtil.isEmptyIfStr(rowList.get(5).toString().trim()) && !StrUtil.isEmptyIfStr(rowList.get(6).toString().trim())) {
                    String[] leaderEmployeeName = rowList.get(5).toString().trim().split(",");
                    String[] leaderEmployeePhone = rowList.get(6).toString().trim().split(",");
                    if (leaderEmployeeName.length != leaderEmployeePhone.length) {
                        rowList.add(0, "分管领导名称和电话数量不一致，必须是一一对应");
                        errList.add(rowList);
                        return;
                    }
                    for (int i = 0; i < leaderEmployeeName.length; i++) {
                        if (!employeeMap.containsKey(leaderEmployeeName[i].trim() + ":" + leaderEmployeePhone[i].trim())) {
                            rowList.add(0, "分管领导不存在，请确认员工名称和电话是否有误");
                            errList.add(rowList);
                            return;
                        }
                        if (i == 0) {
                            leaderIds = employeeMap.get(leaderEmployeeName[i].trim() + ":" + leaderEmployeePhone[i].trim()).toString();
                        } else {
                            leaderIds = leaderIds + "," + employeeMap.get(leaderEmployeeName[i].trim() + ":" + leaderEmployeePhone[i].trim()).toString();
                        }
                    }
                }
                if (!StrUtil.isEmptyIfStr(rowList.get(7).toString().trim())) {
                    String orgSectorName = rowList.get(7).toString().trim();
                    Integer orgSector = OrgSectorEnum.getValueByName(orgSectorName);
                    if (orgSector == null) {
                        rowList.add(0, "机构板块只能填写[集团总部、公用事业、金融投资、现代农业、工程地产、其他板块]");
                        errList.add(rowList);
                        return;
                    }
                }
                if (!StrUtil.isEmptyIfStr(rowList.get(8).toString().trim())) {
                    String unitPropertiesName = rowList.get(8).toString().trim();
                    Integer unitProperties = UnitPropertiesEnum.getValueByName(unitPropertiesName);
                    if (unitProperties == null) {
                        rowList.add(0, "单位性质只能填写[合并报表企业、托管企业、其他]");
                        errList.add(rowList);
                        return;
                    }
                }
                if (!StrUtil.isEmptyIfStr(rowList.get(11).toString().trim())) {
                    String code = rowList.get(11).toString().trim();
                    if (!codeMap.containsKey(code)) {
                        rowList.add(0, "更新部门,单位编码不存在");
                        errList.add(rowList);
                        return;
                    }
                }
                HrmDept hrmDept = new HrmDept();
                hrmDept.setParentId(codeMap.get(rowList.get(2).toString().trim()).getDeptId());
                hrmDept.setDeptType("公司".equals(rowList.get(1).toString().trim()) ? 1 : 2);
                hrmDept.setName(rowList.get(0).toString().trim());
                hrmDept.setMainEmployeeId(mainId);
                hrmDept.setLeaderEmployeeId(leaderIds);
                hrmDept.setOrgSector(StrUtil.isEmptyIfStr(rowList.get(7).toString().trim()) ? null : OrgSectorEnum.getValueByName(rowList.get(7).toString().trim()));
                hrmDept.setUnitProperties(StrUtil.isEmptyIfStr(rowList.get(8).toString().trim()) ? null : UnitPropertiesEnum.getValueByName(rowList.get(8).toString().trim()));
                hrmDept.setLevel(codeMap.get(rowList.get(2).toString().trim()).getLevel() + 1);
                hrmDept.setSortId(StrUtil.isEmptyIfStr(rowList.get(9).toString().trim()) ? null : Long.parseLong(rowList.get(9).toString().trim()));
                hrmDept.setSectionChiefPreparation(StrUtil.isEmptyIfStr(rowList.get(10).toString().trim()) ? null : Long.parseLong(rowList.get(10).toString().trim()));
                hrmDept.setSectionChiefNum(StrUtil.isEmptyIfStr(rowList.get(11).toString().trim()) ? null : Long.parseLong(rowList.get(10).toString().trim()));
                hrmDept.setDeputySectionChiefPreparation(StrUtil.isEmptyIfStr(rowList.get(11).toString().trim()) ? null : Long.parseLong(rowList.get(11).toString().trim()));
                hrmDept.setDeputySectionChiefNum(StrUtil.isEmptyIfStr(rowList.get(12).toString().trim()) ? null : Long.parseLong(rowList.get(12).toString().trim()));
                hrmDept.setDirectorPreparation(StrUtil.isEmptyIfStr(rowList.get(13).toString().trim()) ? null : Long.parseLong(rowList.get(12).toString().trim()));
                hrmDept.setDirectorNum(StrUtil.isEmptyIfStr(rowList.get(14).toString().trim()) ? null : Long.parseLong(rowList.get(13).toString().trim()));
                hrmDept.setDeputyDirectorPreparation(StrUtil.isEmptyIfStr(rowList.get(15).toString().trim()) ? null : Long.parseLong(rowList.get(13).toString().trim()));
                hrmDept.setDeputyDirectorNum(StrUtil.isEmptyIfStr(rowList.get(16).toString().trim()) ? null : Long.parseLong(rowList.get(14).toString().trim()));
                if (StrUtil.isEmptyIfStr(rowList.get(12).toString().trim())) {
                    hrmDept.setCode(createDeptCode(hrmDept));
                    addDeptList.add(hrmDept);
                } else {
                    hrmDept.setCode(rowList.get(12).toString().trim());
                    lambdaUpdate().eq(HrmDept::getCode, hrmDept.getCode()).update(hrmDept);
                }
            } else {
                if (rowIndex == 1) {
                    rowList.add(0, "错误信息");
                }
                errList.add(Convert.toInt(rowIndex), rowList);
            }
        });
        if (!addDeptList.isEmpty()) {
            this.saveBatch(addDeptList);
        }
        FileUtil.del(filePath);
        JSONObject result = new JSONObject().fluentPut("totalSize", num.get()).fluentPut("errSize", 0);
        int listSize = 2;
        if (errList.size() > listSize) {
            File errFile = FileUtil.file("excelData/" + IdUtil.simpleUUID() + ".xlsx");
            BigExcelWriter writer = ExcelUtil.getBigWriter(errFile);
            // 取消数据的黑色边框以及数据左对齐
            CellStyle cellStyle = writer.getCellStyle();
            cellStyle.setFillBackgroundColor(IndexedColors.BLACK.getIndex());
            cellStyle.setBorderTop(BorderStyle.NONE);
            cellStyle.setBorderBottom(BorderStyle.NONE);
            cellStyle.setBorderLeft(BorderStyle.NONE);
            cellStyle.setBorderRight(BorderStyle.NONE);
            cellStyle.setAlignment(HorizontalAlignment.LEFT);
            Font defaultFont = writer.createFont();
            defaultFont.setFontHeightInPoints((short) 11);
            cellStyle.setFont(defaultFont);
            // 取消数字格式的数据的黑色边框以及数据左对齐
            CellStyle cellStyleForNumber = writer.getStyleSet().getCellStyleForNumber();
            cellStyleForNumber.setBorderTop(BorderStyle.NONE);
            cellStyleForNumber.setBorderBottom(BorderStyle.NONE);
            cellStyleForNumber.setBorderLeft(BorderStyle.NONE);
            cellStyleForNumber.setBorderRight(BorderStyle.NONE);
            cellStyleForNumber.setAlignment(HorizontalAlignment.LEFT);
            cellStyleForNumber.setFillBackgroundColor(IndexedColors.BLACK.getIndex());
            cellStyleForNumber.setFont(defaultFont);

            CellStyle textStyle = writer.getWorkbook().createCellStyle();
            DataFormat format = writer.getWorkbook().createDataFormat();
            textStyle.setDataFormat(format.getFormat("@"));

            writer.merge(errList.get(1).size() + 1, errList.get(0).get(0).toString().trim(), true);
            writer.getHeadCellStyle().setAlignment(HorizontalAlignment.LEFT);
            writer.getHeadCellStyle().setWrapText(true);
            Font headFont = writer.createFont();
            headFont.setFontHeightInPoints((short) 11);
            writer.getHeadCellStyle().setFont(headFont);
            writer.getHeadCellStyle().setFillPattern(FillPatternType.NO_FILL);
            writer.getOrCreateRow(0).setHeightInPoints(120);
            writer.setRowHeight(-1, 20);

            //writer.merge(6, "系统用户导入模板(*)为必填项");
            for (int i = 0; i < errList.get(1).size(); i++) {
                writer.getSheet().setDefaultColumnStyle(i, textStyle);
            }
            errList.remove(0);
            writer.write(errList);
            writer.close();
            //将错误信息的excel保存七天 604800 七天的秒数
            MultipartFile multipartFile = MultipartFileUtil.getMultipartFile(errFile);
            UploadEntity uploadEntity = adminFileService.uploadTempFile(multipartFile, IdUtil.simpleUUID()).getData();

            redis.setex(AdminCacheKey.UPLOAD_EXCEL_MESSAGE_PREFIX + "file:" + uploadEntity.getFileId(), 604800, uploadEntity.getPath());

            result.fluentPut("errSize", errList.size() - 1).fluentPut("token", uploadEntity.getFileId());

        }
        //保存操作记录
        HrmEmployeeDataChangeRecord record = new HrmEmployeeDataChangeRecord();
        record.setType(EmployeeDataChangeType.DEPT.getValue());
        record.setSubDeptId(EmployeeHolder.getEmployeeInfo().getDeptId());
        record.setSubEmployeeId(EmployeeHolder.getEmployeeInfo().getEmployeeId());
        record.setRemark(String.format("员工 %s 通过EXCEL导入了部门信息。", EmployeeHolder.getEmployeeInfo().getEmployeeName()));
        employeeDataChangeRecordService.addChangeRecord(record);
        return result;
    }

    private String getFilePath(MultipartFile file) {
        String dirPath = FileUtil.getTmpDirPath();
        try {
            InputStream inputStream = file.getInputStream();
            File fromStream = FileUtil.writeFromStream(inputStream, dirPath + "/" + IdUtil.simpleUUID() + file.getOriginalFilename());
            return fromStream.getAbsolutePath();
        } catch (IOException e) {
            throw new CrmException(SystemCodeEnum.SYSTEM_UPLOAD_FILE_ERROR);
        }
    }

    @Override
    public UploadEntity uploadTempFile(MultipartFile file, String batchId) {
        Result<UploadEntity> result = adminFileService.uploadTempFile(file, batchId);
        return result.getData();
    }

    @Override
    public Set<Long> getParentDeptIdList(List<Long> deptIdList) {
        Set<Long> deptIdSet = new HashSet<>();
        if (deptIdList == null || deptIdList.isEmpty()) {
            return deptIdSet;
        }
        List<HrmDept> list = lambdaQuery().list();
        Map<Long, HrmDept> deptMap = new HashMap<>();
        if (list != null && !list.isEmpty()) {
            deptMap = list.stream().collect(Collectors.toMap(HrmDept::getDeptId, Function.identity(), (o1, o2) -> o2));
        }
        for (Long deptId : deptIdList) {
            deptIdSet.add(deptId);
            if (deptMap.get(deptId) != null) {
                getParentDeptId(deptMap, deptMap.get(deptId).getParentId(), deptIdSet);
            }
        }
        return deptIdSet;
    }

    private Set<Long> getParentDeptId(Map<Long, HrmDept> deptMap, Long deptId, Set<Long> result) {
        if (deptMap.containsKey(deptId)) {
            result.add(deptId);
            getParentDeptId(deptMap, deptMap.get(deptId).getParentId(), result);
        }
        return result;
    }

    @Override
    public List<DeptEmployeeDataTotalVO> employeeDataTotal(DeptEmployeeDataTotalVO dataTotalVO) {
        if (StringUtils.isEmpty(dataTotalVO.getTotalDate())) {
            throw new CrmException(SystemCodeEnum.SYSTEM_NO_VALID);
        }

        List<DeptEmployeeDataTotalVO> deptVOList = new ArrayList<>();
        List<DeptVO> list = new ArrayList<>();
        List<Integer> dataAuthTypeList = adminService.queryDataTypeList(UserUtil.getUserId(), MenuIdConstant.DEPT_MENU_ID).getData();
        if (EmployeeHolder.isHrmAdmin() || dataAuthTypeList.contains(DataAuthEnum.ALL.getValue())) {
            list = deptMapper.queryList(new QueryDeptListBO());
        } else {
            if (!dataAuthTypeList.isEmpty()) {
                QueryDeptListBO queryDeptListBO = new QueryDeptListBO();
                Set<Long> deptIds = employeeUtil.queryDataAuthDeptId(dataAuthTypeList, MenuIdConstant.DEPT_MENU_ID);
                deptIds.add(-1L);
                queryDeptListBO.setDeptIds(deptIds);
                list = deptMapper.queryList(queryDeptListBO);
            }
        }
        List<DeptEmployeeDataTotalVO> deptList = list.stream().map(dept -> BeanUtil.copyProperties(dept, DeptEmployeeDataTotalVO.class)).collect(Collectors.toList());
        deptVOList = getDeptDataTotalTree(0L, deptList, dataTotalVO);
        return deptVOList;
    }

    private List<DeptEmployeeDataTotalVO> getDeptDataTotalTree(Long pid, List<DeptEmployeeDataTotalVO> deptList, DeptEmployeeDataTotalVO dataTotalVO) {
        if (deptList != null && !deptList.isEmpty()) {
            DateTimeFormatter yearMonthFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
            YearMonth yearMonth = YearMonth.parse(dataTotalVO.getTotalDate(), yearMonthFormatter);
            // 获取该月的第一天
            LocalDate firstDay = yearMonth.atDay(1);
            // 获取该月的最后一天
            LocalDate lastDay = yearMonth.atDay(yearMonth.lengthOfMonth());
            //数据完整度检索日期
            LocalDate integrityDate;
            // 获取当前日期
            YearMonth currentYearMonth = YearMonth.now();
            if (yearMonth.equals(currentYearMonth)) {
                integrityDate = LocalDate.now().minusDays(1);
            } else {
                integrityDate = lastDay;
            }
            //查询每一个部门数据完整度
            List<DeptEmployeeDataTotalVO> deptIntegrityList = employeeDataIntegrityMapper.queryDeptDataIntegrityTotal(integrityDate);
            Map<Long, BigDecimal> deptIntegrityMap = new HashMap<>();
            if (deptIntegrityList != null && !deptIntegrityList.isEmpty()) {
                deptIntegrityMap = deptIntegrityList.stream().collect(Collectors.toMap(DeptEmployeeDataTotalVO::getDeptId, DeptEmployeeDataTotalVO::getDataProgress, (o1, o2) -> o2));
            }
            //查询每一个部门异动数
            List<DeptEmployeeDataTotalVO> deptMobilizeList = employeeDataMobilizeRecordMapper.queryDeptMobilizeNumberTotal(firstDay, lastDay);
            Map<Long, Long> deptMobilizeMap = new HashMap<>();
            if (deptMobilizeList != null && !deptMobilizeList.isEmpty()) {
                deptMobilizeMap = deptMobilizeList.stream().collect(Collectors.toMap(DeptEmployeeDataTotalVO::getDeptId, DeptEmployeeDataTotalVO::getMobilizeNumber, (o1, o2) -> o2));
            }
            //查询每一个部门异动数
            List<DeptEmployeeDataTotalVO> deptChangeList = employeeDataChangeRecordMapper.queryDeptChangeNumberTotal(firstDay, lastDay);
            Map<Long, Long> deptChangeMap = new HashMap<>();
            if (deptChangeList != null && !deptChangeList.isEmpty()) {
                deptChangeMap = deptChangeList.stream().collect(Collectors.toMap(DeptEmployeeDataTotalVO::getDeptId, DeptEmployeeDataTotalVO::getChangeNumber, (o1, o2) -> o2));
            }
            //部门分组
            Map<Long, List<DeptEmployeeDataTotalVO>> deptMap = deptList.stream().collect(Collectors.groupingBy(DeptEmployeeDataTotalVO::getParentId, Collectors.toList()));
            //根节点
            List<DeptEmployeeDataTotalVO> deptRoot = deptMap.get(pid);
            getDeptDataChildren(deptRoot, deptMap, deptIntegrityMap, deptMobilizeMap, deptChangeMap);
            return deptRoot;
        }
        return deptList;
    }

    private void getDeptDataChildren(List<DeptEmployeeDataTotalVO> deptRoot, Map<Long, List<DeptEmployeeDataTotalVO>> deptMap, Map<Long, BigDecimal> deptIntegrityMap, Map<Long, Long> deptMobilizeMap, Map<Long, Long> deptChangeMap) {
        if (deptRoot != null && !deptRoot.isEmpty()) {
            for (DeptEmployeeDataTotalVO dept : deptRoot) {
                //异动数
                dept.setMobilizeNumber(Optional.ofNullable(deptMobilizeMap.get(dept.getDeptId())).orElse(0L));
                //修改数
                dept.setChangeNumber(Optional.ofNullable(deptChangeMap.get(dept.getDeptId())).orElse(0L));
                List<DeptEmployeeDataTotalVO> children = deptMap.get(dept.getDeptId());
                getDeptDataChildren(children, deptMap, deptIntegrityMap, deptMobilizeMap, deptChangeMap);
                if (children != null && !children.isEmpty()) {
                    children = children.stream().sorted(Comparator.comparing(DeptEmployeeDataTotalVO::getSortId, Comparator.nullsLast(Long::compare)).thenComparing(DeptEmployeeDataTotalVO::getDeptId)).collect(Collectors.toList());
                    dept.setChildren(children);
                    long count = children.stream().filter(item -> item.getDataProgress() != null && item.getDataProgress().compareTo(BigDecimal.ZERO) > 0).count();
                    if (count == 0L) {
                        dept.setDataProgress(new BigDecimal(0L));
                    } else {
                        //数据完整度
                        BigDecimal total = children.stream().map(DeptEmployeeDataTotalVO::getDataProgress).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal progress = total.divide(BigDecimal.valueOf(count), 2, RoundingMode.HALF_UP);
                        dept.setDataProgress(progress);
                    }
                    //异动数
                    dept.setMobilizeNumber(dept.getMobilizeNumber() + children.stream().mapToLong(DeptEmployeeDataTotalVO::getMobilizeNumber).sum());
                    //人员异动数
                    dept.setChangeNumber(dept.getChangeNumber() + children.stream().mapToLong(DeptEmployeeDataTotalVO::getChangeNumber).sum());
                } else {
                    //数据完整度
                    dept.setDataProgress(Optional.ofNullable(deptIntegrityMap.get(dept.getDeptId())).orElse(BigDecimal.ZERO));
                }
            }
        }
    }

    @Override
    public void updateComprehensiveDept() {
        List<HrmEmployee> employeeList = employeeMapper.selectOrgEmployeeList();
        for (HrmEmployee employee : employeeList) {
            List<DeptVO> deptVOS = deptMapper.selectAllDeptList();
            Map<Long, List<DeptVO>> deptGroup = deptVOS.stream().collect(Collectors.groupingBy(DeptVO::getParentId));
            Map<Long, DeptVO> deptMap = deptVOS.stream().collect(Collectors.toMap(DeptVO::getDeptId, Function.identity()));
            Long deptId = employee.getDeptId();
            Long comprehensiveDeptId = null;
            if (deptGroup.containsKey(deptId)) {
                List<DeptVO> depts = deptGroup.get(deptId);
                for (int i = 0; i < depts.size(); i++) {
                    if ("综合部".equals(depts.get(i).getName())) {
                        comprehensiveDeptId = depts.get(i).getDeptId();
                        break;
                    }
                }
                if (comprehensiveDeptId == null) {
                    DeptVO deptVO = deptMap.get(deptId);
                    //当前机构底下没有综合部
                    AddDeptBO addDeptBO = new AddDeptBO();
                    addDeptBO.setDeptType(2);
                    addDeptBO.setName("综合部");
                    addDeptBO.setOrgSector(deptVO.getOrgSector());
                    addDeptBO.setParentId(deptId);
                    addDeptBO.setUnitProperties(deptVO.getUnitProperties());
                    addDeptBO.setOrgType(deptVO.getOrgType());
                    HrmDept hrmDept = addOrUpdate(addDeptBO);
                    comprehensiveDeptId = hrmDept.getDeptId();
                }
            } else {
                DeptVO deptVO = deptMap.get(deptId);
                //当前机构底下没有综合部
                AddDeptBO addDeptBO = new AddDeptBO();
                addDeptBO.setDeptType(2);
                addDeptBO.setName("综合部");
                addDeptBO.setOrgSector(deptVO.getOrgSector());
                addDeptBO.setParentId(deptId);
                addDeptBO.setUnitProperties(deptVO.getUnitProperties());
                addDeptBO.setOrgType(deptVO.getOrgType());
                HrmDept hrmDept = addOrUpdate(addDeptBO);
                comprehensiveDeptId = hrmDept.getDeptId();
            }
            //修改员工的部门为综合部
            employeeDataService.lambdaUpdate().set(HrmEmployeeData::getFieldValue, comprehensiveDeptId)
                    .set(HrmEmployeeData::getFieldValueDesc, comprehensiveDeptId)
                    .eq(HrmEmployeeData::getFieldName, "dept")
                    .eq(HrmEmployeeData::getEmployeeId, employee.getEmployeeId())
                    .update();
        }
    }

    @Override
    public HashMap<Long, String> getAllDeptPath() {
        HashMap<Long, String> deptPathMap = new HashMap<>();
        List<DeptVO> deptList = deptMapper.selectAllDeptList();
        if (deptList != null && !deptList.isEmpty()) {
            Map<Long, DeptVO> group = deptList.stream().collect(Collectors.toMap(DeptVO::getDeptId, v -> v));
            for (DeptVO dept : deptList) {
                List<String> deptNameList = new ArrayList<>();
                getDeptPath(deptNameList, group, dept.getDeptId());
                deptPathMap.put(dept.getDeptId(), String.join("/", deptNameList));
            }
        }
        return deptPathMap;
    }
}
